package cn.itsource.user.service.impl;

import cn.itsource.basic.constant.PetHomeConstans;
import cn.itsource.basic.constant.VerificationConstant;
import cn.itsource.basic.constant.WechatConstant;
import cn.itsource.basic.exception.CustomException;
import cn.itsource.basic.util.HttpClientUtils;
import cn.itsource.user.domain.LoginInfo;
import cn.itsource.user.domain.User;
import cn.itsource.user.domain.Wechat;
import cn.itsource.user.domain.dto.LogininfoDto;
import cn.itsource.user.mapper.LoginInfoMapper;
import cn.itsource.user.mapper.UserMapper;
import cn.itsource.user.mapper.WechatMapper;
import cn.itsource.user.service.IWechatService;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
public class WechatServiceImpl implements IWechatService {

    @Autowired
    private WechatMapper mapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private LoginInfoMapper loginInfoMapper;
    @Autowired
    private UserMapper userMapper;

    /**
     * 处理回调接口
     * @param code
     * @return
     */
    @Override
    public Map<String, Object> handleCallback(String code) {
        //获取token的url地址
        String tokenUrl = WechatConstant.TOKEN_URL.replace("APPID", WechatConstant.APPID).replace("SECRET", WechatConstant.SECRET)
                .replace("CODE", code);
        //通过授权码获取token令牌
        String tokenJsonStr = HttpClientUtils.httpGet(tokenUrl);
        //把json字符串转为json对象
        JSONObject jsonObject = JSONObject.parseObject(tokenJsonStr);
        //获取token
        String access_token = jsonObject.getString("access_token");
        //获取openid  微信用户唯一标识
        String openid = jsonObject.getString("openid");
        //获取微信用户资源url地址
        String redirectUrl = WechatConstant.USERINFO_URL.replace("ACCESS_TOKEN", access_token).replace("OPENID", openid);
        //发送get请求 通过redirectUrl获取用户资源
        String redirectUrlJsonStr = HttpClientUtils.httpGet(redirectUrl);
        //把json字符串转为json对象
        jsonObject = JSONObject.parseObject(redirectUrlJsonStr);
        //System.out.println(jsonObject);

        //将openid传到前端
        HashMap<String, Object> map = new HashMap<>();
        //根据openid这个微信用户唯一标识 查询数据库 查询（t_wxuser  t_logininfo）
        Wechat wechat = mapper.queryByOpenid(openid);
        //判断是否第一次扫码 如果第一次扫码就添加t_wxuser
        if (wechat == null) {
            wechat = new Wechat();
            wechat.setOpenid(openid);
            wechat.setNickname(jsonObject.getString("nickname"));
            wechat.setSex(jsonObject.getInteger("sex"));
            wechat.setAddress(jsonObject.getString("country") + jsonObject.getString("province") + jsonObject.getString("city"));
            wechat.setHeadimgurl(jsonObject.getString("headimgurl"));
            //保存wx用户基本信息
            mapper.save(wechat);
            //将openid放入map 返回map 跳转到绑定手机号页面
            map.put("openid", openid);
            return map;
        } else {
            LoginInfo loginInfo = wechat.getLogininfo();
            //不是第一次扫码就判断logininfo是否为空 为空就跳转绑定手机号页面
            if (loginInfo == null) {
                map.put("openid", openid);
                return map;
            } else {
                //不都是第一次扫码（也就是wechat不为空）并且以绑定就跳转index
                //将token 和 loginUser 传到前端
                String token = UUID.randomUUID().toString();
                //保存在redis里
                redisTemplate.opsForValue().set(token, loginInfo,30, TimeUnit.MINUTES);
                map.put("token", token);
                map.put("loginUser",loginInfo );
                return map;
            }
        }

    }

    @Override
    public Map<String, Object> binderPhone(LogininfoDto logininfoDto) throws CustomException {
        //校验数据
        CheckData(logininfoDto);
        //通过手机号查看数据库该账户是否存在 存在就直接绑定 不存在就添加 然后进行绑定
        LoginInfo loginInfo =loginInfoMapper.getLoginInfo(logininfoDto.getPhone(), logininfoDto.getType());
        if (loginInfo == null) {
            //创建logininfo
            loginInfo = creatLogininfo(logininfoDto);
            //添加save
            loginInfoMapper.register(loginInfo);
            //添加user
            User user = creatUser(loginInfo);
            userMapper.save(user);
        }
        //绑定微信
        mapper.binder(logininfoDto.getOpenid(),loginInfo);
        //添加token loginuser
        HashMap<String, Object> map = new HashMap<>();
        String token = UUID.randomUUID().toString();
        //redis设置
        redisTemplate.opsForValue().set(token, loginInfo,30,TimeUnit.MINUTES);
        map.put("token", token);
        map.put("loginUser", loginInfo);
        return map;
    }

    private User creatUser(LoginInfo loginInfo) {
        User user = new User();
        BeanUtils.copyProperties(loginInfo,user );
        user.setState(PetHomeConstans.OK);
        user.setLogininfo(loginInfo);
        return user;
    }

    private LoginInfo creatLogininfo(LogininfoDto logininfoDto) {
        LoginInfo logininfo = new LoginInfo();
        BeanUtils.copyProperties(logininfoDto, logininfo);
        return logininfo;
    }

    private void CheckData(LogininfoDto logininfoDto) throws CustomException {
        //手机号不能为空
        if (logininfoDto.getPhone() == null) {
            throw  new CustomException("手机号不能为空");
        }
        //验证码不能为空
        if (logininfoDto.getCode() == null) {
            throw new  CustomException("验证码不能为空");
        }
        String binderCode = (String) redisTemplate.opsForValue().get(logininfoDto.getPhone() + ":" + VerificationConstant.USER_Binder);
        System.out.println(binderCode);
        //验证码已过期
        if (StringUtils.isEmpty(binderCode)){
            throw new  CustomException("验证码已过期");
        }
        //验证码错误
        if(!logininfoDto.getCode().equals(binderCode.split(":")[0])){
            throw new  CustomException("验证码错误");
        }


    }
}
